#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2008 Thibauld Favre <tfavre@gmail.com>
#
# Author:
#  Thibauld Favre
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA

import os
import datetime
import urllib2
import tidy
import zipfile
from FeedSyncGen import FeedSync, FeedSyncFactory
from multipart import Part, Multipart, FilePart

def discoverLocalApps():
    pipe = os.popen("dpkg -l | awk '/^ii/ {print $2}'")
    apps = {}
    for line in pipe:
        apps[line.strip()] = None
    return apps

def upload(filename, filepath):
    params = {
            'rq_key':local_config['api_key'],
            'token':local_config['device_token'],
            'method':'appsFeed'
            }
    url = 'http://api.savemyconf.com/upload.php';
    params = api.encode_and_sign(params,False)
    body = Multipart()
    for k,v in params.iteritems():
        part = Part({'name': k}, v)
        body.attach(part)
    zip_feed_path = filepath+'.zip'
    z = zipfile.ZipFile(zip_feed_path,'w',zipfile.ZIP_DEFLATED)
    z.write(filepath,'local_apps_feed.xml')
    z.close()
    filepart = FilePart({'name': filename}, zip_feed_path, 'application/zip')
    body.attach(filepart)
    request = urllib2.Request(url)
    request.add_data(str(body))
    (header, value) = body.header()
    request.add_header(header, value)
    return urllib2.urlopen(request)

def createFeed(target_filename,token):
    feed = FeedSync(
        title = "Device Applications Feed",
        link = "http://www.savemyconf.com",
        description = "Applications installed on device",
        lastBuildDate = datetime.datetime.now(),
        since = datetime.datetime.now(),
        until = datetime.datetime.now()
    )
    apps = discoverLocalApps()
    for k,v in apps.iteritems():
        feed.addItem(title = k, id=k+'_'+token, endPoint=token)
    options = dict(input_xml=1,output_xml=1,add_xml_decl=1,indent=1)
    f = open(target_filename,"w")
    f.write(str(tidy.parseString(feed.to_xml(),**options)))
    f.close()

def updateFeed(filepath,token):
    fs = FeedSyncFactory()
    feed = fs.createFromFeed(filepath)
    items_to_update = {}
    local_items = discoverLocalApps()
    for feed_item in feed.items:
        if (feed_item.title in local_items) and (feed_item.deleted()):
            items_to_update[feed_item.title] = 'undelete'
        elif (feed_item.title not in local_items) and (not feed_item.deleted()):
            items_to_update[feed_item.title] = 'delete'
        local_items[feed_item.title.strip()] = feed_item.sync_attr['id']
    for k,v in local_items.iteritems():
        if v is None:
            items_to_update[k] = 'add'
    for k,v in items_to_update.iteritems():
        if v=='add':
            feed.addItem(title=k, id=k+'_'+token, endPoint=token)
        elif v=='delete':
            feed.deleteItem(local_items[k],token)
        elif v=='undelete':
            feed.undeleteItem(local_items[k],token)
    options = dict(input_xml=1,output_xml=1,add_xml_decl=1,indent=1)
    f = open(filepath,"w")
    f.write(str(tidy.parseString(feed.to_xml(),**options)))
    f.close()

token = local_config['device_token']
apps_feed =  str(os.path.join(local_config['data_dir'],'local_apps_feed.xml')) # due to unclear (to me at least) unicode related issues, the str() call is important here
if not os.path.isfile(apps_feed): # if the feed does not exist, we initialize it
    createFeed(apps_feed,token)
else: 
    f = open(apps_feed,"r")
    if not f.read(): # if the feed exist but is empty, we initialize it
        f.close()
        createFeed(apps_feed,token)
    else: # if the feed already exists, we update it
        f.close()
        updateFeed(apps_feed,token)

if token != 'no_token':
    upload('apps_feed',apps_feed) # we upload the updated feed
